import db from './db'
import Log from './log'
import Consts from '../assets/consts'

let log = new Log('foo', Log.levelVerbose)

const what = Consts.im.what
const arg1 = Consts.im.arg1
const arg2 = Consts.im.arg2
const custom = Consts.im.custom
const imdb = Consts.im.db
const imtables = Consts.im.db.tables

let foo = {
  handle: (handler, what, arg1, arg2, obj) => {
    if (null != handler) {
      handler(what, arg1, arg2, obj)
    }
  },

  str2json: str => {
    let json = {}

    if (null != str) {
      try {
        json = JSON.parse(str)
      } catch (e) {
      }
    }

    return json
  },

  s2a1: data => 'success' === data.status ? arg1.success : arg1.fail,

  sidTodo: sid => {
    let to = sid.split('-')

    if (null != to && 2 === to.length
        && (('team' === to[0] && to[1].length > 0)
            || ('p2p' === to[0] /* && to[1].startsWith(Consts.imAppSecret) */))) {
    } else {
      throw new Error('bad sid')
    }

    return to
  },

  teamCbTodo: data => ({
    team: data.teamId || (data.team ? data.team.teamId : null),
    name: data.name || (data.team ? data.team.name : null),

    owner: data.team ? data.team.owner : null,
    accounts: data.accounts || null,

    origin: data
  }),

  msgTodo: msg => ({
    session: msg.sessionId || msg.scene + '-' + msg.from,
    ts: msg.time,
    status: msg.status,

    type: msg.type,
    text: msg.text || null,
    custom: foo.str2json(msg.custom),
    content: foo.str2json(msg.content),

    // [Neo] .file
    file: msg.file || null,
    // [Neo] .notification
    attach: msg.attach || null,

    scene: msg.scene,
    from: msg.from,
    to: msg.to,
    id: msg.idClient,

    origin: msg
  }),

  sessionTodo: s => {
    const to = foo.sidTodo(s.id)

    if (s.hasOwnProperty('lastMsg')) {
      const msg = foo.msgTodo(s.lastMsg)

      let unread = s.unread
      if (custom.type === msg.type && custom.recall === msg.custom.type) {
        unread -= 1

        if (unread < 0) {
          unread = 0
        }
      }

      return {
        session: s.id,
        unread: unread,

        ts: s.updateTime,
        remote: s.msgReceiptTime || 0,

        pin: 0,
        mute: 0,
        ignore: 0,

        scene: to[0],
        target: to[1],

        message: msg,
        origin: s,
      }
    } else {
      return {
        session: s.id,
        unread: 0,

        ts: s.updateTime,
        remote: s.msgReceiptTime || 0,

        pin: 0,
        mute: 0,
        ignore: 0,

        scene: to[0],
        target: to[1],

        message: null,
        origin: s,
      }
    }

  },

  id4session: sid => {
    const to = foo.sidTodo(sid)

    return {
      session: sid,
      unread: 0,

      ts: 0,
      remote: 0,

      pin: 0,
      mute: 0,
      ignore: 0,

      scene: to[0],
      target: to[1],

      message: null,
      origin: null
    }
  },

  msg4session: (msg, ignore = 0) => {
    const to = foo.sidTodo(msg.session)

    return {
      session: msg.session,
      unread: 0,

      ts: msg.ts,
      remote: 0,

      pin: 0,
      mute: 0,
      ignore: ignore,

      scene: to[0],
      target: to[1],

      message: msg,
      origin: null
    }
  },

  msgs2session: (account, msgs) => {
    const count = msgs.length
    let lastMsg = msgs[count - 1]

    console.log('msgs2session', msgs[0].session, msgs.length)

    db.open(imdb.prefix + account)
    .then(e => db.add(e, imtables.message.name, msgs))
    .then(e => db.update(e, imtables.session.name, lastMsg.session, v => {
      if (null == v) {
        v = foo.msg4session(lastMsg)
      }

      msgs.forEach(m => {
        if (m.ts > v.ignore) {

          if (custom.type === m.type && custom.recall === m.custom.type) {
            v.unread -= 1

            if (v.unread < 0) {
              v.unread = 0
            }
          } else {
            v.unread += 1
          }

        }
      })

      v.ts = v.ts > lastMsg.ts ? v.ts : lastMsg.ts
      v.message = lastMsg

      return v
    }))
    .catch(e => log.e(e))
  },

  sortByPinAndTs: (a, b) => {
    if (1 === a.pin && 0 === b.pin) {
      return -1;
    } else if (0 === a.pin && 1 === b.pin) {
      return 1;
    } else {
      return b.ts - a.ts;
    }
  },

}

export default foo;
